import UIKit

/* XCode15的Swift版本5.9 */

/* Swift协议 */
// 类似于Java中的接口
// 一类可以遵守多个协议
// 可以同时继承和遵守协议，需要将父类的名称放在协议名称的前面
// 遵守多个协议时各个协议用逗号分隔
//

protocol Person {
    // 协议属性
    // 协议中通常用变量来声明实例属性，并在类型声明后加上{get set}或者{get}来表示属性是读写的还是可读的
    var name: String {get set}
    var age: Int {get}
    // 关联类型
    // 在协议定义的时候无法确定属性被实现时的具体类型
    // 或者协议在不同的实现时有不同的类型
    associatedtype UnknownType
    var weight: UnknownType {get}
    // 协议方法
    // 可以是实例方法也可以是类方法
    func description()
    // 协议中的构造器
    init(name: String, age: Int, weight: UnknownType)
}

class Student {
    var name: String
    var age: Int
    // 关联类型在遵守该协议的类中确定具体的类型
    var weight: Double
    init(){
        name = ""
        age = 0
        weight = 0.0
    }
    // 协议中的构造器遵守的类一定要实现，并且加上required
    required init(name: String, age: Int, weight: UnknownType) {
        self.name = name
        self.age = age
        self.weight = weight
    }
}

// 还可以在拓展中声明类遵守一个协议
// 注意，只有有一个extension声明了遵守一个协议，其他整体即遵守这个协议
extension Student: Person {
    func description() {
        print("\(name) is \(age)")
    }
}

let theStudent = Student(name: "Tom", age: 23, weight: 69.2)
theStudent.description()

// 协议的继承
protocol protocolPerson {
    var name: String {get set}
    var age: Int {get}
    associatedtype UnknownType
    var weight: UnknownType {get}
    func personDescription()
}

protocol protocolStudent {
    var school: String {get set}
    func studentDescription()
}
protocol protocolGraduate: protocolPerson, protocolStudent {
    var supervisor: String {get set}
    func graduateDescription()
}

class ComputerAssociationMember: protocolGraduate {
    var name : String = ""
    var age : Int
    var weight: Double
    var school: String
    var supervisor : String
    func personDescription() {
        print("It's person description")
    }
    func studentDescription() {
        print("It's student description")
    }
    func graduateDescription() {
        print("It's graduate description")
    }
    init (name: String, age: Int, weight: Double, school : String, supervisor : String){
        self.name = name
        self.age = age
        self.weight = weight
        self.school = school
        self.supervisor = supervisor
    }
}

let theMember = ComputerAssociationMember (name: "Tom", age: 23, weight: 69.2, school: "BUAA", supervisor: "Ian" )
theMember.personDescription()
theMember.studentDescription()
theMember.graduateDescription()
    
/* Swift泛型 */
// 泛型函数
// 在函数名后面加上<T>，表示类型名占位，用来替代具体的类型名
// 在函数的参数列表中，参数a和b的类型均为T，说明a和b是同一种类型
// 当参数为某个类型，那么T就是那个类型
func swap2Element<T>(a : inout T, b: inout T){
    let temp = a
    a = b
    b = temp
}

var a = 3
var b = 5
var c = "Hello"
var d = "world"

swap2Element(a: &a, b: &b)
swap2Element(a: &c, b: &d)
print("a is \(a), b is \(b)")
print("c is \(c), d is \(d)")

// 泛型类
class Car {
    var brand: String
    init (brand: String) {
        self.brand = brand
    }
}

class Bike {
    var speed: Int
    init (speed: Int) {
        self.speed = speed
    }
}

// 在定义阶段无法确定的一种类型，这个类型在类实例化的时候才能确定
class Driver<Vehicle> {
    var name: String
    var vehicle: Vehicle
    init (name: String, vehicle: Vehicle) {
        self.name = name
        self.vehicle = vehicle
    }
}

let porscheCar = Car(brand: "Porsche")
let driverTom = Driver<Car>(name: "Tom", vehicle: porscheCar)
let giantBike = Bike(speed: 50)
// 指定类型的符合也可以不写，将自动确定
let driverSam = Driver(name: "Sam", vehicle: giantBike)
